use nom::{IResult, branch::alt, error_position};

pub fn word_format(words:&str) -> Vec<String> {
    let word_vec:Vec<_> = words.split(&[' ','-','_']).collect();
    vec![
        word_vec.join(" "),
        word_vec.join("-"),
        word_vec.join("_")
    ]
}

pub fn match_word_format(s:&str,words:&str) -> bool {
    let word_fmts = word_format(words);
    for word_fmt in word_fmts {
        if s == word_fmt {
            return true;
        }
    }
    false
}

pub fn words<'a>(words:&'static str) -> impl Fn(&'a str)->IResult<&'a str,&'a str> {
    let word_fmts = word_format(words);
    move |raw_str|{
        let inp = raw_str;
        for word_fmt in &word_fmts {
            if let Some(rest_raw_str) = raw_str.strip_prefix(word_fmt.as_str()) {
                return Ok((rest_raw_str,&raw_str[0..word_fmt.len()]));
            }
        }
        Err(nom::Err::Error(error_position!(inp, nom::error::ErrorKind::TagBits)))
    }   
}

pub fn words_single_test(word:&'static str,raw_str:&'static str) -> Result<(),Box<dyn std::error::Error>> {
    let (rest_raw_str,match_words) = words(word)(raw_str)?;
    println!("{} match {} get ({},{})",raw_str,word,rest_raw_str,match_words);
    Ok(())
}

pub fn words_mix_test(raw_str:&'static str) -> Result<(),Box<dyn std::error::Error>> {
    let (rest_raw_str,match_words) = alt((
        words("chunking method"),
        words("chunking algorithm"),
    ))(raw_str)?;
    
    println!("{} match chunking-method&chunking-algorithm get ({},{})",raw_str,rest_raw_str,match_words);
    Ok(())
}

pub fn words_lifetime_test<'a>(raw_str:&'a str) -> Result<(),Box<dyn std::error::Error+'a>> {
    let (rest_raw_str,match_words) = words("a bc d")(raw_str)?;
    println!("{} match a bc d get ({},{})",raw_str,rest_raw_str,match_words);
    Ok(())
}

pub fn words_test()-> Result<(),Box<dyn std::error::Error>> {
    words_lifetime_test("a-bc-defg")?;
    words_mix_test("chunking-algorithm")?;
    words_single_test("chunking method", "chunking methodccbcaibiue")?;
    words_single_test("chunking method", "chunking-methodandivanvna")?;
    words_single_test("chunking method", "chunking_methodlvabvibsvb")?;
    let err = words_single_test("chunking method", "chunking  habacibca").expect_err("");
    println!("err info {}",err);
    Ok(())
}